#include <sdk.h>
#include <wx/aui/aui.h>
#include <wx/listbook.h>
#include "configurationpanel.h"
#include "environmentsettingsdlg.h"
#include "M_Code_colourmanager.h"

const wxString base_imgs[] = {
  _T( "general-prefs" ),
  _T( "view" ),
  _T( "notebook-appearance" ),
  _T( "colours" ),
  _T( "colours" ),
  _T( "dialogs" ),
  _T( "net" )
};
const int IMAGES_COUNT = sizeof( base_imgs ) / sizeof( wxString );

BEGIN_EVENT_TABLE( EnvironmentSettingsDlg, wxScrollingDialog )
  EVT_BUTTON( XRCID( "btnAuiCaptionColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnAuiCaptionTextColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnAuiActiveCaptionColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnAuiActiveCaptionGradientColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnAuiActiveCaptionTextColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnAuiInactiveCaptionColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnAuiInactiveCaptionGradientColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnAuiInactiveCaptionTextColour" ), EnvironmentSettingsDlg::OnChooseColour )
  EVT_BUTTON( XRCID( "btnResetDefaultColours" ), EnvironmentSettingsDlg::OnResetDefaultColours )
  EVT_CHECKBOX( XRCID( "chkAutoHideMessages" ), EnvironmentSettingsDlg::OnAutoHide )
  EVT_RADIOBOX( XRCID( "rbSettingsIconsSize" ), EnvironmentSettingsDlg::OnSettingsIconsSize )
  EVT_CHECKBOX( XRCID( "chkDblClkMaximizes" ), EnvironmentSettingsDlg::OnDblClickMaximizes )
  EVT_CHECKBOX( XRCID( "chkNBUseMousewheel" ), EnvironmentSettingsDlg::OnUseTabMousewheel )
  EVT_CHOICE( XRCID( "chCategory" ), EnvironmentSettingsDlg::OnChooseAppColourCategory )
  EVT_LISTBOX( XRCID( "lstColours" ), EnvironmentSettingsDlg::OnChooseAppColourItem )
  EVT_BUTTON( XRCID( "btnColour" ), EnvironmentSettingsDlg::OnClickAppColour )
  EVT_BUTTON( XRCID( "btnDefaultColour" ), EnvironmentSettingsDlg::OnClickAppColour )
END_EVENT_TABLE()

EnvironmentSettingsDlg::EnvironmentSettingsDlg( wxWindow* parent, wxAuiDockArt* art ) : m_pArt( art ), m_pImageList( nullptr ) {
  ConfigManager *cfg = Manager::Get()->GetConfigManager( _T( "app" ) );
  ConfigManager *pcfg = Manager::Get()->GetConfigManager( _T( "project_manager" ) );
  ConfigManager *mcfg = Manager::Get()->GetConfigManager( _T( "message_manager" ) );
  wxXmlResource* xml_res = wxXmlResource::Get();
  wxString resPath = ConfigManager::GetDataFolder() + _T( "/配置环境.xrc" );
  if( !xml_res->Load( resPath ) )  {
    xml_File_lock = false;
    Manager::Get()->GetLogManager()->LogInf( F( _T( "文件丢失: %s " ), resPath.wx_str() ) );
    return;
  }
  if( !xml_res->LoadObject( this, parent, _T( "dlgEnvironmentSettings" ), _T( "wxScrollingDialog" ) ) ) {
    xml_File_lock = false;
    Manager::Get()->GetLogManager()->LogInf( _T( "资源丢失" ) );
    return;
  }
  xml_File_lock = true;
  XRCCTRL( *this, "wxID_OK", wxButton )->SetDefault();
  LoadListbookImages();
  Connect( XRCID( "nbMain" ), wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, wxListbookEventHandler( EnvironmentSettingsDlg::OnPageChanging ) );
  Connect( XRCID( "nbMain" ), wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED, wxListbookEventHandler( EnvironmentSettingsDlg::OnPageChanged ) );
  XRCCTRL( *this, "chkModifiedFiles", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/check_modified_files" ),   true ) );
  XRCCTRL( *this, "chkInvalidTargets", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/ignore_invalid_targets" ), true ) );
  XRCCTRL( *this, "rbAppStart", wxRadioBox )->SetSelection( cfg->ReadBool( _T( "/environment/blank_workspace" ), true ) ? 1 : 0 );
  XRCCTRL( *this, "chkProjectLayout", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/enable_project_layout" ),  true ) );
  XRCCTRL( *this, "chkEditorLayout", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/enable_editor_layout" ),   false ) );
  wxTextCtrl* txt = XRCCTRL( *this, "txtConsoleShell", wxTextCtrl );
  txt->SetValue( cfg->Read( _T( "/console_shell" ), DEFAULT_CONSOLE_SHELL ) );
  wxComboBox *combo = XRCCTRL( *this, "cbConsoleTerm", wxComboBox );
  combo->Append( DEFAULT_CONSOLE_TERM );
  combo->Append( _T( "terminal -t $TITLE -x " ) );
  wxString terminal = cfg->Read( _T( "/console_terminal" ), DEFAULT_CONSOLE_TERM );
  if( !combo->SetStringSelection( terminal ) ) {
    combo->Insert( terminal, 0 );
    combo->SetStringSelection( terminal );
  }
  const wxString &openFolderCommand = cfg->Read( _T( "/open_containing_folder" ), cbDEFAULT_OPEN_FOLDER_CMD );
  XRCCTRL( *this, "txtOpenFolder", wxTextCtrl )->SetValue( openFolderCommand );
  XRCCTRL( *this, "rbProjectOpen", wxRadioBox )->SetSelection( pcfg->ReadInt( _T( "/open_files" ), 1 ) );
  XRCCTRL( *this, "rbSettingsIconsSize", wxRadioBox )->SetSelection( cfg->ReadInt( _T( "/environment/settings_size" ), 0 ) );
  XRCCTRL( *this, "spnLogFontSize", wxSpinCtrl )->SetValue( mcfg->ReadInt( _T( "/log_font_size" ), 8 ) );
  bool en = mcfg->ReadBool( _T( "/auto_hide" ), false );
  XRCCTRL( *this, "chkAutoHideMessages", wxCheckBox )->SetValue( en );
  XRCCTRL( *this, "chkAutoShowMessagesOnSearch", wxCheckBox )->SetValue( mcfg->ReadBool( _T( "/auto_show_search" ), true ) );
  XRCCTRL( *this, "chkAutoShowMessagesOnWarn", wxCheckBox )->SetValue( mcfg->ReadBool( _T( "/auto_show_build_warnings" ), true ) );
  XRCCTRL( *this, "chkAutoShowMessagesOnErr", wxCheckBox )->SetValue( mcfg->ReadBool( _T( "/auto_show_build_errors" ), true ) );
  XRCCTRL( *this, "chkAutoShowMessagesOnSearch", wxCheckBox )->Enable( en );
  XRCCTRL( *this, "chkAutoShowMessagesOnWarn", wxCheckBox )->Enable( en );
  XRCCTRL( *this, "chkAutoShowMessagesOnErr", wxCheckBox )->Enable( en );
  XRCCTRL( *this, "chkAutoFocusMessagesOnErr", wxCheckBox )->SetValue( mcfg->ReadBool( _T( "/auto_focus_build_errors" ), true ) );
  XRCCTRL( *this, "chkSaveSelectionChangeInMP", wxCheckBox )->SetValue( mcfg->ReadBool( _T( "/save_selection_change_in_mp" ), true ) );
  en = cfg->ReadBool( _T( "/environment/view/dbl_clk_maximize" ), true );
  XRCCTRL( *this, "chkDblClkMaximizes", wxCheckBox )->SetValue( en );
  int idx = Manager::Get()->GetAppFrame()->GetMenuBar()->FindMenu( _T( "视图(&V)" ) );
  if( idx != wxNOT_FOUND ) {
    wxMenu* menuView = Manager::Get()->GetAppFrame()->GetMenuBar()->GetMenu( idx );
    int sub_idx = menuView->FindItem( _T( "窗口布局" ) );
    if( sub_idx != wxNOT_FOUND ) {
      wxMenu* menuLayouts = menuView->FindItem( sub_idx )->GetSubMenu();
      if( menuLayouts ) {
        wxMenuItemList& items = menuLayouts->GetMenuItems();
        for( size_t i = 0; i < items.GetCount() && ! items[i]->IsSeparator() ; ++i ) {
          XRCCTRL( *this, "choLayoutToToggle", wxChoice )->Append( items[i]->GetLabelText( items[i]->GetItemLabelText() ) );
        }
      }
    }
  }
  int sel = XRCCTRL( *this, "choLayoutToToggle", wxChoice )->FindString( cfg->Read( _T( "/environment/view/layout_to_toggle" ), cfg->Read( _T( "/main_frame/layout/default" ) ) ) );
  XRCCTRL( *this, "choLayoutToToggle", wxChoice )->SetSelection( sel != wxNOT_FOUND ? sel : 0 );
  XRCCTRL( *this, "choLayoutToToggle", wxChoice )->Enable( en );
  XRCCTRL( *this, "chkListTabs", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/tabs_list" ), 0 ) );
  XRCCTRL( *this, "chkStackedBasedTabSwitching", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/tabs_stacked_based_switching" ), 0 ) );
  bool enableTabMousewheel = cfg->ReadBool( _T( "/environment/tabs_use_mousewheel" ), true );
  bool modToAdvance = cfg->ReadBool( _T( "/environment/tabs_mousewheel_advance" ), false );
  XRCCTRL( *this, "chkNBUseMousewheel", wxCheckBox )->SetValue( enableTabMousewheel );
  XRCCTRL( *this, "rbNBModToAdvance", wxRadioButton )->SetValue( modToAdvance );
  XRCCTRL( *this, "rbNBModToMove", wxRadioButton )->SetValue( !modToAdvance );
  XRCCTRL( *this, "chkNBInvertAdvance", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/tabs_invert_advance" ), false ) );
  XRCCTRL( *this, "chkNBInvertMove", wxCheckBox )->SetValue( cfg->ReadBool( _T( "/environment/tabs_invert_move" ), false ) );
  XRCCTRL( *this, "txtMousewheelModifier", wxTextCtrl )->SetValue( cfg->Read( _T( "/environment/tabs_mousewheel_modifier" ), _T( "Ctrl" ) ) );
  XRCCTRL( *this, "txtMousewheelModifier", wxTextCtrl )->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( EnvironmentSettingsDlg::OnMousewheelModifier ) );
  XRCCTRL( *this, "rbNBModToAdvance", wxRadioButton )->Enable( enableTabMousewheel );
  XRCCTRL( *this, "rbNBModToMove", wxRadioButton )->Enable( enableTabMousewheel );
  XRCCTRL( *this, "chkNBInvertAdvance", wxCheckBox )->Enable( enableTabMousewheel );
  XRCCTRL( *this, "chkNBInvertMove", wxCheckBox )->Enable( enableTabMousewheel );
  XRCCTRL( *this, "txtMousewheelModifier", wxTextCtrl )->Enable( enableTabMousewheel );
  XRCCTRL( *this, "spnAuiBorder", wxSpinCtrl )->SetValue( cfg->ReadInt( _T( "/environment/aui/border_size" ), m_pArt->GetMetric( wxAUI_DOCKART_PANE_BORDER_SIZE ) ) );
  XRCCTRL( *this, "spnAuiSash", wxSpinCtrl )->SetValue( cfg->ReadInt( _T( "/environment/aui/sash_size" ), m_pArt->GetMetric( wxAUI_DOCKART_SASH_SIZE ) ) );
  XRCCTRL( *this, "spnAuiCaption", wxSpinCtrl )->SetValue( cfg->ReadInt( _T( "/environment/aui/caption_size" ), m_pArt->GetMetric( wxAUI_DOCKART_CAPTION_SIZE ) ) );
  XRCCTRL( *this, "btnAuiActiveCaptionColour", wxButton )->SetBackgroundColour( cfg->ReadColour( _T( "/environment/aui/active_caption_colour" ), m_pArt->GetColour( wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR ) ) );
  XRCCTRL( *this, "btnAuiActiveCaptionGradientColour", wxButton )->SetBackgroundColour( cfg->ReadColour( _T( "/environment/aui/active_caption_gradient_colour" ), m_pArt->GetColour( wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR ) ) );
  XRCCTRL( *this, "btnAuiActiveCaptionTextColour", wxButton )->SetBackgroundColour( cfg->ReadColour( _T( "/environment/aui/active_caption_text_colour" ), m_pArt->GetColour( wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR ) ) );
  XRCCTRL( *this, "btnAuiInactiveCaptionColour", wxButton )->SetBackgroundColour( cfg->ReadColour( _T( "/environment/aui/inactive_caption_colour" ), m_pArt->GetColour( wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR ) ) );
  XRCCTRL( *this, "btnAuiInactiveCaptionGradientColour", wxButton )->SetBackgroundColour( cfg->ReadColour( _T( "/environment/aui/inactive_caption_gradient_colour" ), m_pArt->GetColour( wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR ) ) );
  XRCCTRL( *this, "btnAuiInactiveCaptionTextColour", wxButton )->SetBackgroundColour( cfg->ReadColour( _T( "/environment/aui/inactive_caption_text_colour" ), m_pArt->GetColour( wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR ) ) );
  XRCCTRL( *this, "txtProxy", wxTextCtrl )->SetValue( cfg->Read( _T( "/network_proxy" ) ) );
  FillApplicationColours();
  AddPluginPanels();
  GetSizer()->SetSizeHints( this );
  CentreOnParent();
  Layout();
}

EnvironmentSettingsDlg::~EnvironmentSettingsDlg() {
  delete m_pImageList;
}

void EnvironmentSettingsDlg::AddPluginPanels() {
  const wxString base = _T( "images/settings/" );
  const wxString noimg = _T( "images/settings/generic-plugin" );
  wxListbook* lb = XRCCTRL( *this, "nbMain", wxListbook );
  Manager::Get()->GetPluginManager()->GetConfigurationPanels( ~( cgCompiler | cgEditor ), lb, m_PluginPanels );
  for( size_t i = 0; i < m_PluginPanels.GetCount(); ++i ) {
    cbConfigurationPanel* panel = m_PluginPanels[i];
    panel->SetParentDialog( this );
    lb->AddPage( panel, panel->GetTitle() );
    wxString onFile = ConfigManager::LocateDataFile( base + panel->GetBitmapBaseName() + _T( ".png" ), sdDataGlobal | sdDataUser );
    if( onFile.IsEmpty() ) {
      onFile = ConfigManager::LocateDataFile( noimg + _T( ".png" ), sdDataGlobal | sdDataUser );
    }
    wxString offFile = ConfigManager::LocateDataFile( base + panel->GetBitmapBaseName() + _T( "-off.png" ), sdDataGlobal | sdDataUser );
    if( offFile.IsEmpty() ) {
      offFile = ConfigManager::LocateDataFile( noimg + _T( "-off.png" ), sdDataGlobal | sdDataUser );
    }
    m_pImageList->Add( M_Code_LoadBitmap( onFile ) );
    m_pImageList->Add( M_Code_LoadBitmap( offFile ) );
    lb->SetPageImage( lb->GetPageCount() - 1, m_pImageList->GetImageCount() - 2 );
  }
  UpdateListbookImages();
}

void EnvironmentSettingsDlg::LoadListbookImages() {
  const wxString base = ConfigManager::GetDataFolder() + _T( "/images/settings/" );
  m_pImageList = new wxImageList( 80, 80 );
  wxBitmap bmp;
  for( int i = 0; i < IMAGES_COUNT; ++i ) {
    bmp = M_Code_LoadBitmap( base + base_imgs[i] + _T( ".png" ) );
    m_pImageList->Add( bmp );
    bmp = M_Code_LoadBitmap( base + base_imgs[i] + _T( "-off.png" ) );
    m_pImageList->Add( bmp );
  }
}

void EnvironmentSettingsDlg::UpdateListbookImages() {
  wxListbook* lb = XRCCTRL( *this, "nbMain", wxListbook );
  int sel = lb->GetSelection();
  if( SettingsIconsStyle( XRCCTRL( *this, "rbSettingsIconsSize", wxRadioBox )->GetSelection() ) == sisNoIcons ) {
    SetSettingsIconsStyle( lb->GetListView(), sisNoIcons );
    lb->SetImageList( nullptr );
  } else {
    lb->SetImageList( m_pImageList );
    for( size_t i = 0; i < IMAGES_COUNT + m_PluginPanels.GetCount(); ++i ) {
      lb->SetPageImage( i, ( i * 2 ) + ( sel == ( int )i ? 0 : 1 ) );
    }
    SetSettingsIconsStyle( lb->GetListView(), sisLargeIcons );
  }
  wxString label = lb->GetPageText( sel );
  while( label.Replace( _T( " & " ), _T( " && " ) ) ) ;
  XRCCTRL( *this, "lblBigTitle", wxStaticText )->SetLabel( label );
  XRCCTRL( *this, "pnlTitleInfo", wxPanel )->Layout();
}

void EnvironmentSettingsDlg::OnPageChanging( M_Code_unused wxListbookEvent& event ) {
}

void EnvironmentSettingsDlg::OnPageChanged( wxListbookEvent& event ) {
  if( event.GetOldSelection() != -1 && event.GetSelection() != -1 ) {
    UpdateListbookImages();
  }
  Layout();
}

void EnvironmentSettingsDlg::OnChooseColour( wxCommandEvent& event ) {
  wxColourData data;
  wxWindow* sender = FindWindowById( event.GetId() );
  data.SetColour( sender->GetBackgroundColour() );
  wxColourDialog dlg( this, &data );
  PlaceWindow( &dlg );
  if( dlg.ShowModal() == wxID_OK ) {
    wxColour colour = dlg.GetColourData().GetColour();
    sender->SetBackgroundColour( colour );
  }
}

void EnvironmentSettingsDlg::OnResetDefaultColours( M_Code_unused wxCommandEvent& event ) {
  wxAuiDockArt* art = new wxAuiDefaultDockArt;
  XRCCTRL( *this, "spnAuiBorder", wxSpinCtrl )->SetValue( art->GetMetric( wxAUI_DOCKART_PANE_BORDER_SIZE ) );
  XRCCTRL( *this, "spnAuiSash", wxSpinCtrl )->SetValue( art->GetMetric( wxAUI_DOCKART_SASH_SIZE ) );
  XRCCTRL( *this, "spnAuiCaption", wxSpinCtrl )->SetValue( art->GetMetric( wxAUI_DOCKART_CAPTION_SIZE ) );
  XRCCTRL( *this, "btnAuiActiveCaptionColour", wxButton )->SetBackgroundColour( art->GetColour( wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR ) );
  XRCCTRL( *this, "btnAuiActiveCaptionGradientColour", wxButton )->SetBackgroundColour( art->GetColour( wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR ) );
  XRCCTRL( *this, "btnAuiActiveCaptionTextColour", wxButton )->SetBackgroundColour( art->GetColour( wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR ) );
  XRCCTRL( *this, "btnAuiInactiveCaptionColour", wxButton )->SetBackgroundColour( art->GetColour( wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR ) );
  XRCCTRL( *this, "btnAuiInactiveCaptionGradientColour", wxButton )->SetBackgroundColour( art->GetColour( wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR ) );
  XRCCTRL( *this, "btnAuiInactiveCaptionTextColour", wxButton )->SetBackgroundColour( art->GetColour( wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR ) );
  delete art;
}

void EnvironmentSettingsDlg::OnAutoHide( M_Code_unused wxCommandEvent& event ) {
  bool en = XRCCTRL( *this, "chkAutoHideMessages", wxCheckBox )->GetValue();
  XRCCTRL( *this, "chkAutoShowMessagesOnSearch", wxCheckBox )->Enable( en );
  XRCCTRL( *this, "chkAutoShowMessagesOnWarn", wxCheckBox )->Enable( en );
  XRCCTRL( *this, "chkAutoShowMessagesOnErr", wxCheckBox )->Enable( en );
}

void EnvironmentSettingsDlg::OnDblClickMaximizes( M_Code_unused wxCommandEvent& event ) {
  XRCCTRL( *this, "choLayoutToToggle", wxChoice )->Enable( event.IsChecked() );
}

void EnvironmentSettingsDlg::OnMousewheelModifier( M_Code_unused wxKeyEvent& event ) {
  wxString keys;
  if( wxGetKeyState( WXK_SHIFT ) ) {
    keys += keys.IsEmpty() ? _T( "Shift" ) : _T( "+Shift" );
  }
  if( wxGetKeyState( WXK_CONTROL ) ) {
    keys += keys.IsEmpty() ? _T( "Ctrl" ) : _T( "+Ctrl" );
  }
  if( wxGetKeyState( WXK_ALT ) ) {
    keys += keys.IsEmpty() ? _T( "Alt" ) : _T( "+Alt" );
  }
  if( !keys.IsEmpty() ) {
    XRCCTRL( *this, "txtMousewheelModifier", wxTextCtrl )->SetValue( keys );
  }
}

void EnvironmentSettingsDlg::OnUseTabMousewheel( M_Code_unused wxCommandEvent& event ) {
  bool en = ( bool )XRCCTRL( *this, "chkNBUseMousewheel", wxCheckBox )->GetValue();
  XRCCTRL( *this, "rbNBModToAdvance", wxRadioButton )->Enable( en );
  XRCCTRL( *this, "rbNBModToMove", wxRadioButton )->Enable( en );
  XRCCTRL( *this, "chkNBInvertAdvance", wxCheckBox )->Enable( en );
  XRCCTRL( *this, "chkNBInvertMove", wxCheckBox )->Enable( en );
}

void EnvironmentSettingsDlg::OnSettingsIconsSize( wxCommandEvent& event ) {
  UpdateListbookImages();
  Layout();
}

void EnvironmentSettingsDlg::EndModal( int retCode ) {
  if( retCode == wxID_OK ) {
    ConfigManager *cfg = Manager::Get()->GetConfigManager( _T( "app" ) );
    ConfigManager *pcfg = Manager::Get()->GetConfigManager( _T( "project_manager" ) );
    ConfigManager *mcfg = Manager::Get()->GetConfigManager( _T( "message_manager" ) );
    cfg->Write( _T( "/environment/check_modified_files" ), ( bool ) XRCCTRL( *this, "chkModifiedFiles", wxCheckBox )->GetValue() );
    cfg->Write( _T( "/environment/ignore_invalid_targets" ), ( bool ) XRCCTRL( *this, "chkInvalidTargets", wxCheckBox )->GetValue() );
    cfg->Write( _T( "/console_shell" ), XRCCTRL( *this, "txtConsoleShell", wxTextCtrl )->GetValue() );
    cfg->Write( _T( "/console_terminal" ), XRCCTRL( *this, "cbConsoleTerm", wxComboBox )->GetValue() );
    cfg->Write( _T( "/open_containing_folder" ), XRCCTRL( *this, "txtOpenFolder", wxTextCtrl )->GetValue() );
    cfg->Write( _T( "/environment/blank_workspace" ), ( bool ) XRCCTRL( *this, "rbAppStart", wxRadioBox )->GetSelection() ? true : false );
    cfg->Write( _T( "/environment/enable_project_layout" ), ( bool ) XRCCTRL( *this, "chkProjectLayout", wxCheckBox )->GetValue() );
    cfg->Write( _T( "/environment/enable_editor_layout" ), ( bool ) XRCCTRL( *this, "chkEditorLayout", wxCheckBox )->GetValue() );
    pcfg->Write( _T( "/open_files" ), ( int )  XRCCTRL( *this, "rbProjectOpen", wxRadioBox )->GetSelection() );
    cfg->Write( _T( "/environment/settings_size" ), ( int )  XRCCTRL( *this, "rbSettingsIconsSize", wxRadioBox )->GetSelection() );
    mcfg->Write( _T( "/auto_hide" ), ( bool ) XRCCTRL( *this, "chkAutoHideMessages", wxCheckBox )->GetValue() );
    mcfg->Write( _T( "/auto_show_search" ), ( bool ) XRCCTRL( *this, "chkAutoShowMessagesOnSearch", wxCheckBox )->GetValue() );
    mcfg->Write( _T( "/auto_show_build_warnings" ), ( bool ) XRCCTRL( *this, "chkAutoShowMessagesOnWarn", wxCheckBox )->GetValue() );
    mcfg->Write( _T( "/auto_show_build_errors" ), ( bool ) XRCCTRL( *this, "chkAutoShowMessagesOnErr", wxCheckBox )->GetValue() );
    mcfg->Write( _T( "/auto_focus_build_errors" ), ( bool ) XRCCTRL( *this, "chkAutoFocusMessagesOnErr", wxCheckBox )->GetValue() );
    mcfg->Write( _T( "/save_selection_change_in_mp" ), ( bool ) XRCCTRL( *this, "chkSaveSelectionChangeInMP", wxCheckBox )->GetValue() );
    cfg->Write( _T( "/environment/view/dbl_clk_maximize" ), ( bool )XRCCTRL( *this, "chkDblClkMaximizes", wxCheckBox )->GetValue() );
    cfg->Write( _T( "/environment/view/layout_to_toggle" ),    XRCCTRL( *this, "choLayoutToToggle", wxChoice )->GetStringSelection() );
    mcfg->Write( _T( "/log_font_size" ), ( int )  XRCCTRL( *this, "spnLogFontSize", wxSpinCtrl )->GetValue() );
    cfg->Write( _T( "/environment/tabs_list" ), ( bool ) XRCCTRL( *this, "chkListTabs", wxCheckBox )->GetValue() );
    bool tab_switcher_mode = ( bool ) XRCCTRL( *this, "chkStackedBasedTabSwitching", wxCheckBox )->GetValue();
    if( Manager::Get()->GetConfigManager( _T( "app" ) )->ReadBool( _T( "/environment/tabs_stacked_based_switching" ) ) != tab_switcher_mode ) {
      if( tab_switcher_mode ) {
        Manager::Get()->GetEditorManager()->RebuildNotebookStack();
      } else
      { Manager::Get()->GetEditorManager()->DeleteNotebookStack(); }
    }
    cfg->Write( _T( "/environment/tabs_stacked_based_switching" ),          tab_switcher_mode );
    bool enableMousewheel = ( bool ) XRCCTRL( *this, "chkNBUseMousewheel", wxCheckBox )->GetValue();
    cfg->Write( _T( "/environment/tabs_use_mousewheel" ), enableMousewheel );
    wxString key = XRCCTRL( *this, "txtMousewheelModifier", wxTextCtrl )->GetValue();
    cfg->Write( _T( "/environment/tabs_mousewheel_modifier" ), key.IsEmpty() ? _T( "Ctrl" ) : key );
    cfg->Write( _T( "/environment/tabs_mousewheel_advance" ), ( bool ) XRCCTRL( *this, "rbNBModToAdvance", wxRadioButton )->GetValue() );
    cfg->Write( _T( "/environment/tabs_invert_advance" ), ( bool ) XRCCTRL( *this, "chkNBInvertAdvance", wxCheckBox )->GetValue() );
    cfg->Write( _T( "/environment/tabs_invert_move" ), ( bool ) XRCCTRL( *this, "chkNBInvertMove", wxCheckBox )->GetValue() );
    M_Code_AuiNotebook::AllowScrolling( enableMousewheel );
    M_Code_AuiNotebook::SetModKeys( cfg->Read( _T( "/environment/tabs_mousewheel_modifier" ), _T( "Ctrl" ) ) );
    M_Code_AuiNotebook::UseModToAdvance( cfg->ReadBool( _T( "/environment/tabs_mousewheel_advance" ), false ) );
    M_Code_AuiNotebook::InvertAdvanceDirection( cfg->ReadBool( _T( "/environment/tabs_invert_advance" ), false ) );
    M_Code_AuiNotebook::InvertMoveDirection( cfg->ReadBool( _T( "/environment/tabs_invert_move" ), false ) );
    cfg->Write( _T( "/environment/aui/border_size" ), ( int )  XRCCTRL( *this, "spnAuiBorder", wxSpinCtrl )->GetValue() );
    cfg->Write( _T( "/environment/aui/sash_size" ), ( int )  XRCCTRL( *this, "spnAuiSash", wxSpinCtrl )->GetValue() );
    cfg->Write( _T( "/environment/aui/caption_size" ), ( int )  XRCCTRL( *this, "spnAuiCaption", wxSpinCtrl )->GetValue() );
    cfg->Write( _T( "/environment/aui/active_caption_colour" ), XRCCTRL( *this, "btnAuiActiveCaptionColour", wxButton )->GetBackgroundColour() );
    cfg->Write( _T( "/environment/aui/active_caption_gradient_colour" ), XRCCTRL( *this, "btnAuiActiveCaptionGradientColour", wxButton )->GetBackgroundColour() );
    cfg->Write( _T( "/environment/aui/active_caption_text_colour" ), XRCCTRL( *this, "btnAuiActiveCaptionTextColour", wxButton )->GetBackgroundColour() );
    cfg->Write( _T( "/environment/aui/inactive_caption_colour" ), XRCCTRL( *this, "btnAuiInactiveCaptionColour", wxButton )->GetBackgroundColour() );
    cfg->Write( _T( "/environment/aui/inactive_caption_gradient_colour" ), XRCCTRL( *this, "btnAuiInactiveCaptionGradientColour", wxButton )->GetBackgroundColour() );
    cfg->Write( _T( "/environment/aui/inactive_caption_text_colour" ), XRCCTRL( *this, "btnAuiInactiveCaptionTextColour", wxButton )->GetBackgroundColour() );
    m_pArt->SetMetric( wxAUI_DOCKART_PANE_BORDER_SIZE, XRCCTRL( *this, "spnAuiBorder", wxSpinCtrl )->GetValue() );
    m_pArt->SetMetric( wxAUI_DOCKART_SASH_SIZE, XRCCTRL( *this, "spnAuiSash", wxSpinCtrl )->GetValue() );
    m_pArt->SetMetric( wxAUI_DOCKART_CAPTION_SIZE, XRCCTRL( *this, "spnAuiCaption", wxSpinCtrl )->GetValue() );
    m_pArt->SetColour( wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR, XRCCTRL( *this, "btnAuiActiveCaptionColour", wxButton )->GetBackgroundColour() );
    m_pArt->SetColour( wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR,  XRCCTRL( *this, "btnAuiActiveCaptionGradientColour", wxButton )->GetBackgroundColour() );
    m_pArt->SetColour( wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR, XRCCTRL( *this, "btnAuiActiveCaptionTextColour", wxButton )->GetBackgroundColour() );
    m_pArt->SetColour( wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, XRCCTRL( *this, "btnAuiInactiveCaptionColour", wxButton )->GetBackgroundColour() );
    m_pArt->SetColour( wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR, XRCCTRL( *this, "btnAuiInactiveCaptionGradientColour", wxButton )->GetBackgroundColour() );
    m_pArt->SetColour( wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR, XRCCTRL( *this, "btnAuiInactiveCaptionTextColour", wxButton )->GetBackgroundColour() );
    cfg->Write( _T( "/network_proxy" ), XRCCTRL( *this, "txtProxy", wxTextCtrl )->GetValue() );
    WriteApplicationColours();
    for( size_t i = 0; i < m_PluginPanels.GetCount(); ++i ) {
      cbConfigurationPanel* panel = m_PluginPanels[i];
      panel->OnApply();
    }
    Manager::Get()->GetColourManager()->Save();
  } else {
    for( size_t i = 0; i < m_PluginPanels.GetCount(); ++i ) {
      cbConfigurationPanel* panel = m_PluginPanels[i];
      panel->OnCancel();
    }
  }
  wxScrollingDialog::EndModal( retCode );
}

namespace {
  struct AppColoursClientData : wxClientData {
    AppColoursClientData( const wxString &id_ ) : id( id_ ) {}

    wxString id;
  };

}

void EnvironmentSettingsDlg::FillApplicationColours() {
  wxListBox *list = XRCCTRL( *this, "lstColours", wxListBox );
  wxChoice *categories = XRCCTRL( *this, "chCategory", wxChoice );
  bool fillCategories = ( categories->GetCount() == 0 );
  std::set<wxString> setCategories;
  wxString category = categories->GetStringSelection();
  if( categories->GetSelection() == 0 ) {
    category = wxEmptyString;
  }
  list->Clear();
  const ColourManager::ColourDefMap &colours = Manager::Get()->GetColourManager()->GetColourDefinitions();
  for( ColourManager::ColourDefMap::const_iterator it = colours.begin(); it != colours.end(); ++it ) {
    if( !it->second.IsValid() ) {
      continue;
    }
    if( category.empty() ) {
      list->Append( it->second.category + _T( " : " ) + it->second.name, new AppColoursClientData( it->first ) );
    } else if( category == it->second.category ) {
      list->Append( it->second.name, new AppColoursClientData( it->first ) );
    }
    if( fillCategories ) {
      setCategories.insert( it->second.category );
    }
  }
  if( fillCategories ) {
    categories->Append( _T( "All" ) );
    categories->Select( 0 );
    for( std::set<wxString>::const_iterator it = setCategories.begin(); it != setCategories.end(); ++it ) {
      categories->Append( *it );
    }
  }
  wxCommandEvent tempEvent;
  OnChooseAppColourItem( tempEvent );
}

void EnvironmentSettingsDlg::OnChooseAppColourCategory( M_Code_unused wxCommandEvent &event ) {
  FillApplicationColours();
}

void EnvironmentSettingsDlg::OnChooseAppColourItem( wxCommandEvent &event ) {
  wxButton *btnColour = XRCCTRL( *this, "btnColour", wxButton );
  wxButton *btnDefault = XRCCTRL( *this, "btnDefaultColour", wxButton );
  const AppColoursClientData *data = static_cast<AppColoursClientData*>( event.GetClientObject() );
  if( !data ) {
    btnColour->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
    btnDefault->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
    btnColour->Enable( false );
    btnDefault->Enable( false );
    return;
  }
  const ColourManager::ColourDefMap &colours = Manager::Get()->GetColourManager()->GetColourDefinitions();
  const ColourManager::ColourDefMap::const_iterator it = colours.find( data->id );
  if( it != colours.end() ) {
    std::map<wxString, wxColour>::const_iterator colourIt = m_ChangedAppColours.find( data->id );
    if( colourIt != m_ChangedAppColours.end() ) {
      btnColour->SetBackgroundColour( colourIt->second );
    } else
    { btnColour->SetBackgroundColour( it->second.value ); }
    btnDefault->SetBackgroundColour( it->second.defaultValue );
    btnColour->Enable( true );
    btnDefault->Enable( true );
  } else {
    btnColour->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
    btnDefault->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
    btnColour->Enable( false );
    btnDefault->Enable( false );
  }
}

void EnvironmentSettingsDlg::OnClickAppColour( wxCommandEvent &event ) {
  wxListBox *list = XRCCTRL( *this, "lstColours", wxListBox );
  if( list->GetSelection() == wxNOT_FOUND ) {
    return;
  }
  const AppColoursClientData *data;
  data = static_cast<AppColoursClientData*>( list->GetClientObject( list->GetSelection() ) );
  if( !data ) {
    return;
  }
  const ColourManager::ColourDefMap &colours = Manager::Get()->GetColourManager()->GetColourDefinitions();
  const ColourManager::ColourDefMap::const_iterator it = colours.find( data->id );
  if( it == colours.end() ) {
    return;
  }
  wxColour oldColour = it->second.value;
  std::map<wxString, wxColour>::iterator changedIt = m_ChangedAppColours.find( data->id );
  if( changedIt != m_ChangedAppColours.end() ) {
    oldColour = changedIt->second;
  }
  wxButton *btnColour = XRCCTRL( *this, "btnColour", wxButton );
  if( event.GetId() == XRCID( "btnColour" ) ) {
    wxColourData colour;
    colour.SetColour( oldColour );
    wxColourDialog dlg( this, &colour );
    if( dlg.ShowModal() == wxID_OK ) {
      m_ChangedAppColours[data->id] = dlg.GetColourData().GetColour();
      btnColour->SetBackgroundColour( dlg.GetColourData().GetColour() );
    }
  } else if( event.GetId() == XRCID( "btnDefaultColour" ) ) {
    m_ChangedAppColours[data->id] = it->second.defaultValue;
    btnColour->SetBackgroundColour( it->second.defaultValue );
  }
}

void EnvironmentSettingsDlg::WriteApplicationColours() {
  if( m_ChangedAppColours.empty() ) {
    return;
  }
  ColourManager *manager = Manager::Get()->GetColourManager();
  for( std::map<wxString, wxColour>::const_iterator it = m_ChangedAppColours.begin();
       it != m_ChangedAppColours.end();
       ++it ) {
    manager->SetColour( it->first, it->second );
  }
}



wxString EnvironmentSettingsDlg::AnnoyingDlgReturnToString( const wxString& caption ) {
  std::map<wxString, wxString>::const_iterator it = m_AnnoyingDlgReturnMap.find( caption.AfterLast( _T( ':' ) ) );
  if( it != m_AnnoyingDlgReturnMap.end() ) {
    return caption.BeforeLast( _T( ':' ) ) + _T( ':' ) + it->second;
  }
  return caption;
}

wxString EnvironmentSettingsDlg::StringToAnnoyingDlgReturn( const wxString& caption ) {
  for( std::map<wxString, wxString>::const_iterator it = m_AnnoyingDlgReturnMap.begin();
       it != m_AnnoyingDlgReturnMap.end(); ++it ) {
    if( caption.AfterLast( _T( ':' ) ) == it->second ) {
      return caption.BeforeLast( _T( ':' ) ) + _T( ':' ) + it->first;
    }
  }
  return caption;
}
